<template>
  <div class="fx-progress" :class="[status,{circle:type==='circle'}]" :style="progressStyle">
    <div class="progress-line" v-if="type==='line'">
      <div class="line" :style="lineStyle">
        <div class="inline" :class="{active}" :style="inlineStyle">
          <span v-if="inside&&showText" class="mr10">{{ progressText }}</span>
        </div>
      </div>
      <div class="out-text" v-if="!inside&&showText">{{ progressText }}</div>
    </div>
    <div class="progress-circle" v-else-if="type==='circle'">
      <svg viewBox="0 0 100 100">
        <path d="M 50 50 m 0 -47 a 47 47 0 1 1 0 94 a 47 47 0 1 1 0 -94" class="progress-circle-inner"
              :stroke-width="strokeWidth||6" fill="none"/>
        <path v-show="modelValue" d="M 50 50 m 0 -47 a 47 47 0 1 1 0 94 a 47 47 0 1 1 0 -94" :stroke="strokeColor"
              fill="none" stroke-linecap="round" :stroke-width="strokeWidth||6" :style="circlePathStyle"/>
      </svg>
      <span class="fx-progress-text">
        <slot name="icon">{{ progressText }}</slot>
      </span>
    </div>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, PropType, ref } from 'vue'
import { useModelWatch, useThemeColor } from '@/base/hooks'
import { ComponentTypes, componentTypesArr } from '@/base/types'

type ProgressFormat = (val: number) => number | string
type ProgressType = 'line' | 'circle'
type ProgressColor = ({ percentage: number, color: string }[]) | string | ((val: number) => string)

interface ProgressProps {
  modelValue: number;
  strokeWidth: number;
  active: boolean;
  status: ComponentTypes;
  format: ProgressFormat;
  inside: boolean;
  color: ProgressColor;
  showText: boolean;
  type: ProgressType;
  circleWidth: number;
}

const insideHeight = 18

export default defineComponent({
  name: 'FProgress',
  props: {
    modelValue: {
      type: Number as PropType<number>,
      default: 0,
      required: true,
      validator (val: number): boolean {
        return val >= 0 && val <= 100
      }
    },
    // 进度条类型
    type: {
      type: String as PropType<ProgressType>,
      default: 'line'
    },
    // 进度条宽度
    strokeWidth: {
      type: Number as PropType<number>,
      default: 0
    },
    // 类型
    status: {
      type: String as PropType<ComponentTypes>,
      default: 'primary',
      validator (val: ComponentTypes): boolean {
        return componentTypesArr.includes(val)
      }
    },
    // 格式化
    format: {
      type: Function as PropType<ProgressFormat>,
      default: null
    },
    // 进度条内部显示文字
    inside: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    // 颜色集合
    color: {
      type: [Array, Function, String] as PropType<ProgressColor>,
      default: () => []
    },
    // 是否显示文字
    showText: {
      type: Boolean as PropType<boolean>,
      default: true
    },
    // 圆形进度条宽度
    circleWidth: {
      type: Number as PropType<number>,
      default: 126
    },
    // 是否显示进度条动效
    active: {
      type: Boolean as PropType<boolean>,
      default: false
    }
  },
  setup (props: ProgressProps) {
    const progressValue = ref<number>(props.modelValue)
    useModelWatch(() => props.modelValue, progressValue)

    // 默认样式
    const lineStyle = computed(() => {
      const height = props.strokeWidth ? props.strokeWidth : props.inside ? insideHeight : 6
      return {
        height: `${height}px`,
        lineHeight: `${height}px`,
        borderRadius: `${height / 2}px`
      }
    })
    // 默认样式
    const inlineStyle = computed(() => {
      let color: string | null = null
      if (props.color instanceof Array) {
        props.color.forEach(item => {
          if (progressValue.value >= item.percentage) color = item.color
        })
      }
      if (typeof props.color === 'string') {
        color = props.color
      }
      if (typeof props.color === 'function') {
        color = props.color(progressValue.value)
      }
      const height = props.strokeWidth ? props.strokeWidth : props.inside ? insideHeight : 6
      return {
        backgroundColor: color ?? null,
        width: `${progressValue.value}%`,
        borderRadius: `${height / 2}px`
      }
    })

    // 显示进度值
    const progressText = computed(() => {
      if (props.format && typeof props.format === 'function') return props.format(progressValue.value)
      return `${progressValue.value}%`
    })

    // 圆形进度条颜色
    const strokeColor = computed(() => {
      if (props.color instanceof Array && props.color.length) {
        let color = 'rgb(45, 183, 245)'
        props.color.forEach(item => {
          if (progressValue.value >= item.percentage) color = item.color
        })
        return color
      }
      if (typeof props.color === 'string') return props.color
      if (typeof props.color === 'function') return props.color(progressValue.value)
      return useThemeColor(props.status)
    })

    // 圆形进度颜色
    const circlePathStyle = computed(() => {
      return {
        'stroke-dasharray': `${295.31 * props.modelValue / 100}px, 295.31px`
      }
    })

    // 根据进度条类型 返回样式
    const progressStyle = computed(() => {
      if (props.type !== 'circle') return null
      return {
        width: `${props.circleWidth}px`,
        height: `${props.circleWidth}px`
      }
    })

    return {
      progressValue,
      progressText,
      lineStyle,
      inlineStyle,
      strokeColor,
      circlePathStyle,
      progressStyle
    }
  }
})
</script>
